/*
g = RippleGui2.new(MockRipple)
g.colWidth(0)
*/

MockRipple{
	*settings{
		^RippleSettings.new;
	}
}

RippleWidgDec{

	*header{|textWidg|
		^textWidg.font_(Font("Arial Bold", 18))
			.stringColor_(RippleGuiConstants.bigTextColor);
	}
	
	*window{|win|
		
		win.view.background_(MPGuiConstants.getBackground);
		//win.view.keyDownAction = {|view, char, modifiers, unicode, keycode|
		 	//KeyCommands.doCommand(char);
		//};
		^win;
	}
	
	*defaulFont{|elem|
		^elem.font_(RGuiCnst.getDefaultFont);
	}
	
	*recessedElem{|elem|
		this.standard(elem);
		^elem.background_(RippleGuiConstants.getShadeColor)
	}
	
	*standard{|elem|
		elem.canFocus_(false);
		^this.defaulFont(elem);
	}

}

RippleGUI{

	*staticText{ 	|parent, bounds|
		^GUI.staticText(parent, bounds);
	}
	
	*vLayoutView{ |parent, bounds|
		^GUI.vLayoutView.new(parent, bounds)
	}
	
	*button{|parent, bounds|
		^RippleWidgDec.standard(GUI.button.new(parent,bounds));
	}

}

FillWidthFlowLayout : FlowLayout{
	place{|view|
		var vBounds;
		vBounds = view.bounds; 
		view.bounds =  Rect(vBounds.left, vBounds.top, bounds.width - (2 * margin.x), vBounds.height);
		super.place(view);
	}
}


RippleGui2{

	classvar 
		width = 830, 
		height = 738
		;
	
	var containers, mainWindow, rippleMain, rows, cols, elems, rippleMain, voiceButtons;
	var <numPages = 3;
	*new{|parentArg|
		^super.new.init(parentArg)
	}

	init{|parentArg|
		var current;
		rows = [10, 40, 640, 680, height - 10];
		cols = [10, 210, 475, width];
		
		rippleMain = parentArg;
		containers =  Dictionary.new;
		elems = Dictionary.new;
		voiceButtons = Dictionary.new;
		mainWindow = GUI.window.new(
				"(     (    (   ( ((  RIPPLE  )) )   )    )     )", 
				Rect(330,400,width,height)
			)
			.userCanClose_(false)
			.front;
		
			
		RippleWidgDec.window(mainWindow);
		
		RippleWidgDec.header(	
				RippleGUI.staticText.new(mainWindow, this.cellRect(0,0) )
					.string_("Choose a Sample")
			);
		
		RippleWidgDec.header(	
				RippleGUI.staticText.new(mainWindow, this.cellRect(1,0) )
					.string_("Create a Synth")
			);
			
		RippleWidgDec.header(	
				RippleGUI.staticText.new(mainWindow, this.cellRect(2,0))
					.string_("Control a Synth")
			);
			
		RippleWidgDec.header(	
				RippleGUI.staticText.new(mainWindow, this.cellRect(0,2))
					.string_("Load/Save Session")
			);
		
		RippleWidgDec.header(	
				RippleGUI.staticText.new(mainWindow, this.cellRect(1,2))
					.string_("Record Output")
			);
		
		RippleWidgDec.header(	
				RippleGUI.staticText.new(mainWindow, this.cellRect(2,2))
					.string_("Demo Mode")
			);
		
		
		//////////////////////////// DIRECTORY BROWSER AREA ////////////////////////
		current = RippleGUI.vLayoutView(mainWindow,  this.cellRect(0,1, true) );
		containers.add(\dirBrowse->current);
		
		current = RippleWidgDec.recessedElem(
				RippleDirBrowser(current, Rect(0,0, this.colWidth(0, true), this.rowHeight(1) - 40))
			);
		if(rippleMain.settings.get(\defaultSoundDir) != nil,			{
				current.currentDir_(rippleMain.settings.get(\defaultSoundDir));
			}
			
		);
		elems.add(\dirBrowse->current);
		
		RippleGUI.button(containers.at(\dirBrowse),  20@20)
			.states_([["set as default directory",Color.black,RippleGuiConstants.getShadeColor]])
			.action_({
				rippleMain.settings.set(\defaultSoundDir, elems.at(\dirBrowse).currentDir);
			});
			
		
		//////////////////////////// VOICETYPES AREA ////////////////////////
		current = RippleGUI.vLayoutView(mainWindow,  this.cellRect(1,1, true) );
		containers.add(\voicesChooseArea->current);
		
		this.getSynthDescriptors.do{|desc|
			var name, b, class;
			name = desc.name.asString;
			RippleGUI.button(current,200@15)
				.states_([
					[name,Color.black,Color.white]
				])
				.action_({|butt|
					rippleMain.launchSL(desc);
				});			
		};
		if(Animal.notNil){
			
			Animal.subclasses.do{|theClass|
				var name, b, class;
				name = theClass.name.asString;
				b = SCButton(current,200@15);
				b.states = [
					[name,Color.black,Color.yellow],
					[name + "[activated]",Color.yellow,Color.black]
				];
				b.action = {|butt|
					if(butt.value == 1, {
						theClass.getLaunchFn.value;
					},{
						theClass.getKillFn.value;
					});
				};
				b.font_(RGuiCnst.getDefaultFont)	;
			};
			
		};
		
		//////////////////////////// PERSISTANCE AREA ////////////////////////
		current = RippleGUI.vLayoutView(mainWindow,  this.cellRect(0,3, true) );
		containers.add(\persistanceArea->current);
		
		RippleGUI.button(current, 90@20)
			.states_([
				["Load",Color.black,Color.white]
			])
			.action_({		
				CocoaDialog.getPaths({ arg path;
					RipplePersistance.unPack(path[0]);
				})			
			});
		
		RippleGUI.button(current,90@20)
			.states_([
				["Save",Color.black,Color.white]
			])
			.action_({		
				CocoaDialog.savePanel({ arg path;
					RipplePersistance.pack(path);
				})
			});
			
		
		
		//////////////////////////// RECORD AREA ////////////////////////
		current = RippleGUI.vLayoutView(mainWindow,  this.cellRect(1,3, true) );
		containers.add(\recordArea->current);
		
		RippleGUI.button(current, 90@20)
			.states_([
				["Prepare Record", Color.black, Color.white],
				["Record >", Color.red, Color.gray(0.1).alpha_(0.3)],
				["Stop []", Color.black, Color.red.alpha_(0.3)]
			])
			.action = {|recorder|
				if (recorder.value == 1) {
					rippleMain.server.prepareForRecord;
				}{
					if (recorder.value == 2) { rippleMain.server.record } { rippleMain.server.stopRecording };
				};
			};
		
		//////////////////////////// Demo Mode AREA ////////////////////////
		current = RippleGUI.vLayoutView(mainWindow,  this.cellRect(2,3, true) );
		
		
		RippleGUI.button(current, 90@20)
			.states_([
				["Load Demo", Color.black, Color.white]
			])
			.action = {|button|
				RipplePersistance.unPack("Ripple.app/Contents/Resources/Demo/demo1.rpl").do({|voice|
					voice.play;
				});	
			};
		



		//////////////////////////// VOICES AREA ////////////////////////
		
		current = TabbedView(mainWindow,  this.cellRect(2,1, true), ['1','2','3'],[RippleGuiConstants.getShadeColor] );
		containers.add(\voicesArea->current);
		current.views.do({|view|
			view.decorator = FillWidthFlowLayout(view.bounds);	
		});
		
	
	
	}
	
	/////////////////////////////////////////////////////////////
	/////////////////////////////// ACTIONS /////////////////////
	/////////////////////////////////////////////////////////////
	
	selectedVoicePage{
		^containers.at(\voicesArea).views[containers.at(\voicesArea).activeTab]
	}
	
	registerVoice{|voice|
		var b;
		//view.flow({|w|
			b = SCButton(this.selectedVoicePage,240@15);
			b.states = [
				[(voice.getName.copyRange(0,45) + ":" + voice.getSynthType.asString ),Color.black,Color.white]
			];
			b.action = {|butt|
				voice.displayGui;
				Ripple.setActiveVoice(voice);
			};
			b.font_(RGuiCnst.getDefaultFont);
			b.canFocus_(false);
			voiceButtons.add(voice.getName -> b);
		//});		
	}

	deRegisterVoice{|voice|
		var button = voiceButtons.at(voice.getName);
		//voiceButtons.removeAt(voice.getName);
		button.remove;
		//this.selectedVoicePage.remove(voice); // unsafe -- assumes we're removing a voice from current page
		this.selectedVoicePage.refresh;
		this.reflowAll(this.selectedVoicePage);
	}

	
	soundPlayed{|name, time, sustain=false|
		var button;
		button = voiceButtons.at(name);
		if(button.notNil){
			 RippleButtonBlinker.new(button, time, sustain: sustain);
		};
	}
	
	activeVoicePage_{|index|
		index = index.max(0).min(containers.at(\voicesArea).views.size);
		{containers.at(\voicesArea).focus(index)}.defer;
	}
	
	
	//////////////////////////////////////////////////////////////
	/////////////////////////////// UTILITIES /////////////////////
	//////////////////////////////////////////////////////////////
	
	activeVoicePage{
		^containers.at(\voicesArea).activeTab;
	}
	
	getSelectedFilePath{
		^elems.at(\dirBrowse).getSelectedFilePath;
	}
	
	cellRect{|col, row, gutter=false|
		var gutterSize = 0;
		if(gutter){gutterSize = 20}	
		^Rect(cols[col], rows[row], cols[col+1] - cols[col] - gutterSize, rows[row+1] - rows[row] - gutterSize);
	}
	
	// xy is a 0 or 1 value
	cellDim{|xy, index, gutter|
		var data, gutterSize = 0;
		data = [cols,rows].at(xy);
		if( gutter ){
			gutterSize = 20;
		}
		^data[index+1] - data[index] - gutterSize
	}
	
	colWidth{|col, gutter = false|
		^this.cellDim(0, col, gutter);
	}
	
	rowHeight{|row, gutter = false|
		^this.cellDim(1, row, gutter);
	}
	
	bounds{
		^mainWindow.bounds;
	}
	
	getSynthDescriptors{
		var descriptors, getDescendants;
		var t;
		
		
		getDescendants = {|theClass|
			var list, iter;
			list = List.new;
			theClass.subclasses.do{|item|
				list.add(item);
				list.addAll(getDescendants.value(item));		
			};
			list;
		};
		
		descriptors = List.new;
		
		BaseSynthDescriptor.subclasses.do{|theClass|
			descriptors.addAll(getDescendants.value(theClass));
		};
		
		descriptors = descriptors.sort({|a, b|
			a.class.asString <= b.class.asString;
		});
		
		^descriptors 
	}
	
	// this doesn't belong here
	reflowAll {|view|
		view.decorator.reset;
		view.children.do({ |widget|
			if(widget.isKindOf( StartRow ),{
				view.decorator.nextLine
			},{
				view.decorator.place(widget);
			})
		});
	}
	

}